package b_shuzu;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;

/**
 * @ClassName DongtaiShuZu
 * @Description
 * @Author Zhang Li Tao
 * @Date 2024/4/4
 * @Version 1.0
 **/
public class DongTaiShuZu implements Iterable<Integer> {
    public static void main(String[] args) {
        DongTaiShuZu dongTaiShuZu = new DongTaiShuZu();
        dongTaiShuZu.add(1);
        dongTaiShuZu.add(2);
        dongTaiShuZu.add(3);
        dongTaiShuZu.remove(2);

        dongTaiShuZu.foreach(i -> System.out.println(i));
//        while (dongTaiShuZu.hasNext()) {
//            System.out.println(dongTaiShuZu.next());
//        }

//        dongTaiShuZu.stream().forEach(i -> System.out.println(i));

        for (Integer integer : dongTaiShuZu) {
            System.out.println(integer);
        }
    }


    /**
     * 属性：当前容量 当前元素个数 当前数组
     */
    // 容量
    private int capacity = 8;
    // 元素个数
    private int size = 0;
    // 当前数组对象
    private int[] array;

    // 添加元素到末尾
    public void add(int element) {
        add(size, element);
    }

    // 将元素插入到某个指定位置 可能伴随着数组中元素的迁移
    public void add(int index, int element) {
        // 检查是否需要扩容 1.5倍
        checkAndGrow();

        // 索引越界情况
        if (index < 0 || index > size) {
            throw new RuntimeException("IndexOutOfBoundsException");
        }

        // 插入中间位置
        if (index < size) {
            // 调用native系统API 将数组中某一段中的所有元素 往后移动一位 空出一个位置插入元素
            // public static native void arraycopy()
            // 将array的index开始复制到array的index + 1 复制size - index个元素
            System.arraycopy(array, index, array, index + 1, size - index);
        }

        // 插入末尾位置
        array[size] = element;
        size ++;
    }

    // 扩容方法
    public void checkAndGrow() {
        // 如果size为0 则说明第一次调用add 懒加载当前数组对象
        if (size == 0) {
            array = new int[capacity];
        } else if (size == capacity) { // 数组塞满了则扩容
            capacity += capacity >> 1; // 扩容1.5倍

            int[] newArray = new int[capacity]; // 扩容的目标新数组
            // 将array从0开始复制到newArray的0位置开始 复制size个元素
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }
    }

    // 删除某个索引上的元素 涉及元素迁移
    public int remove(int index) {
        // 索引越界情况
        if (index < 0 || index >= size) {
            throw new RuntimeException("IndexOutOfBoundsException");
        }

        int removeElement = array[index];

        // 如果删除最后一个元素不涉及元素迁移
        if (index < size - 1) {
            System.arraycopy(array, index + 1, array, index, size - index - 1);
        }

        // 删除末尾元素 只需要size --即可 后续get时会报错
        // int数组创建出来占用大小已确认 故不存在对象释放这回事
        size --;
        return removeElement;
    }

    // 获取指定索引上的元素
    public int get(int index) {
        if (index < 0 || index >= size) {
            throw new RuntimeException("IndexOutOfBoundsException");
        }

        return array[index];
    }


    // 遍历方式1：模仿foreach 利用Stream流中消费者
    public void foreach(Consumer<Integer> consumer) {
        // 给Consumer多少个元素 就会操作个多少个元素
        for (int i = 0; i < size; i++) {
            consumer.accept(array[i]);
        }
    }

    // 遍历方式2：重写Iterator
    // 记录当前迭代的指针
//    int currentIndex = 0;

    // 只要size大于当前迭代指针 则说明还有元素
//    @Override
//    public boolean hasNext() {
//        return size > currentIndex;
//    }

    // 返回当前迭代指针指向的元素 然后指针加1
//    @Override
//    public Integer next() {
//        return array[currentIndex ++];
//    }

    // 遍历方式3：返回IntStream  让其后续foreach循环
    public IntStream stream() {
        return Arrays.stream(Arrays.copyOfRange(array, 0, size));
    }

    // 遍历方式4：实现Iterable 自行实现Iterator类
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            int currentIndex = 0;

            @Override
            public boolean hasNext() {
                return size > currentIndex;
            }

            @Override
            public Integer next() {
                return array[currentIndex ++];
            }
        };
    }
}
